package com.ls.shiroWithJwt.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * jwt工具类
 */
@Component
public class JwtUtil {

    //token过期时间
    @Value("${jwt.expireTime:3600000}")
    private Long expireTime;

    /**
     * 秘钥
     */
    @Value("${jwt.secretKey:cc!@#dEMiyao}")
    private String secretKey;

    /**
     * 旧秘钥（更换秘钥的过度时期，兼容用以前的秘钥签发的token）
     */
    @Value("${jwt.oldSecretKey:}")
    private String oldSecretKey;

    public static String createToken(Map<String,String> claims) throws Exception {
        Date date = new Date(System.currentTimeMillis()+ instance.expireTime);
        Map<String, Object> map = new HashMap<>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");
        JWTCreator.Builder builder = JWT.create().withHeader(map);
        for(Map.Entry<String, String> entry:claims.entrySet()){
            builder.withClaim(entry.getKey(),entry.getValue());
        }
        return builder.withExpiresAt(date).sign(Algorithm.HMAC256(instance.secretKey));
    }

    public static Map<String,String> verifyToken(String token) throws Exception {
        Map<String,String> result = new HashMap<String,String>();
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(instance.secretKey))
                .build();
        DecodedJWT jwt;
        try{
            jwt = verifier.verify(token);
        }catch (JWTVerificationException e){
            if(instance.oldSecretKey != null && !"".equals(instance.oldSecretKey.trim()))
                jwt = verifier.verify(token);
            else
                throw e;
        }

        Map<String, Claim> claims = jwt.getClaims();
        for(Map.Entry<String,Claim> claim : claims.entrySet()){
            if(claim.getValue() != null)
                result.put(claim.getKey(),claim.getValue().asString());
        }
        return result;
    }


    private static JwtUtil instance;

    @PostConstruct
    public void init(){
        instance = this;
    }

}